﻿using System;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Medianamik.Core.Configuration;
using Medianamik.Core;
using Medianamik.Core.CodeGeneration;
using System.Text.RegularExpressions;
using Medianamik.UI;

namespace TypeManagement
{
    public partial class CodeGeneration : BasePage
    {
        private static CodeGenerationConfigElement _codeGenerationConfig;
        protected static CodeGenerationConfigElement CodeGenerationConfig
        {
            get
            {
                if (_codeGenerationConfig == null)
                {
                    var m = (MedianamikConfigSection)ConfigurationManager.GetSection(ConfigurationSectionName.MEDIANAMIK);
                    _codeGenerationConfig = m.CodeGeneration;
                }
                return _codeGenerationConfig;

            }
        }

        protected string CodeGenerationOutputPath
        {
            get
            {
                return Server.MapPath(CodeGenerationConfig.OutputPath);
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                var types = NodeTypeManager.GetAllTypes(true).Where(t => t.IsGenerated);
                rptTypes.DataSource = types;
                rptTypes.DataBind();

                //Extraction des interfaces utilisées
                var interfaces = (from t in types
                                  from i in t.Interfaces
                                  select (i.NodeTypeInterface)).Distinct()
                                 .OrderBy(i => i.Name);

                rptInterfaces.DataSource = interfaces;
                rptInterfaces.DataBind();
            }
        }

        protected void btnGenerateFiles_Click(object sender, EventArgs e)
        {
            var result = new CodeService().GenerateClientCode(CodeGenerationOutputPath);

            if (result.HasErrors)
            {
                OnCodeGenerationFailure(result);
            }
            else
            {
                OnCodeGenerationSuccess(result);
            }
        }

        protected void OnCodeGenerationSuccess(CodeGenerationResult result)
        {
            Views.SetActiveView(vwSuccess);

            lblDuration.Text = result.Duration.TotalSeconds.ToString("0.00");
        }

        protected void OnCodeGenerationFailure(CodeGenerationResult result)
        {
            Views.SetActiveView(vwFailure);

            //Write compiler output
            var controls = result.CompilerOutput.ToList().ConvertAll<Control>(s => new LiteralControl(s));
            controls.ForEach(delegate(Control c)
            {
                pnlCompilerOutput.Controls.Add(c);
                pnlCompilerOutput.Controls.Add(new LiteralControl("<br />"));
            });

            //Write Errors
            foreach (var error in result.Errors)
            {
                var errorStr = "<a href='#ln" + error.Line + "'>"
                    + error.Line + "</a>&nbsp;"
                   + error.ErrorText;
                phErrors.Controls.Add(new HtmlGenericControl("div") { InnerHtml = errorStr });
            }

            //Write final code
            pnlFinalCode.Controls.Add(new HtmlGenericControl("pre") { InnerHtml = FormatFinalCode(result.FinalCode) });
        }

        /// <summary>
        /// Convert Plain Text to HTML and add line numbers
        /// </summary>
        /// <param name="pInputText"></param>
        /// <returns></returns>
        private string FormatFinalCode(string pInputText)
        {
            //Html Encode
            var finalCodeHTML = HttpUtility.HtmlEncode(pInputText) ?? string.Empty;

            //Add line numbers
            var lineNumber = 1;
            MatchEvaluator evaluator = m => "<span id='ln"
                                            + (lineNumber)
                                            + "' >"
                                            + (lineNumber++)
                                            + "</span> "
                                            + m.Groups[1];

            finalCodeHTML = Regex.Replace(finalCodeHTML, "^(.*)$", evaluator, RegexOptions.Multiline);

            return finalCodeHTML;
        }
    }
}